# Copyright (C) 2025 All rights reserved.
#   
# @File oauth.py
# @Brief 
# @Author 杨嘉祥, vnimy@mediad.cn
# @Version 1.0
# @Date 2025-01-26
#
import frappe
import json
import base64

import frappe.utils
from frappe.utils import oauth
from frappe.utils.oauth import get_oauth2_flow, get_redirect_uri

def get_oauth2_authorize_url(provider: str, redirect_to: str) -> str:
	flow = get_oauth2_flow(provider)
	
	state = {
		"site": frappe.utils.get_url(),
		"token": frappe.generate_hash(),
		"redirect_to": redirect_to,
	}

	# relative to absolute url
	data = {
		"redirect_uri": get_redirect_uri(provider),
		"state": base64.b64encode(bytes(json.dumps(state).encode("utf-8"))),
	}

	oauth2_providers = get_oauth2_providers()

	# additional data if any
	data.update(oauth2_providers[provider].get("auth_url_data", {}))
	
	authorize_url = flow.get_authorize_url(**data)
	if (is_wxwork_browser() or is_wechat_browser()) and authorize_url.startswith("https://open.weixin.qq.com/connect/oauth2/authorize"):
		# 终端使用此参数判断是否需要带上身份信息
		authorize_url += "#wechat_redirect"
	return authorize_url

def get_oauth2_providers() -> dict[str, dict]:
	out = {}
	providers = frappe.get_all("Social Login Key", fields=["*"])

	for provider in providers:
		authorize_url, access_token_url = provider.authorize_url, provider.access_token_url
		if provider.custom_base_url:
			if not is_full_url(authorize_url):
				authorize_url = provider.base_url + provider.authorize_url
			if not is_full_url(access_token_url):
				access_token_url = provider.base_url + provider.access_token_url

		# Keycloak needs this, the base URL also has a route, that urljoin() ignores
		if provider.name == "keycloak":
			provider.api_endpoint = provider.base_url + provider.api_endpoint

		auth_url_data = provider.auth_url_data
		if auth_url_data:
			auth_url_data = json.loads(provider.auth_url_data)
		else:
			auth_url_data = {}

		# 针对企业微信特殊处理
		if provider.is_wxwork:
			default_auth_url_data = {
				"appid": provider.wxwork_agentid,
				"agentid": provider.wxwork_agentid,
			}
			if is_wxwork_browser() or is_wechat_browser():
				# 网页授权登录
				authorize_url = "https://open.weixin.qq.com/connect/oauth2/authorize"
				default_auth_url_data.update({
					"response_type": "code",
					"scope": "snsapi_base",
				})
			else:
				# 扫码登录
				authorize_url = "https://login.work.weixin.qq.com/wwlogin/sso/login"
				default_auth_url_data.update({
					"login_type": "CorpApp",
				})
			for k in default_auth_url_data:
				auth_url_data.setdefault(k, default_auth_url_data.get(k))

		out[provider.name] = {
			"flow_params": {
				"name": provider.name,
				"authorize_url": authorize_url,
				"access_token_url": access_token_url,
				"base_url": provider.base_url,
			},
			"redirect_uri": provider.redirect_url,
			"api_endpoint": provider.api_endpoint,
			"auth_url_data": auth_url_data,
		}

		# if provider.auth_url_data:
		# 	out[provider.name]["auth_url_data"] = json.loads(provider.auth_url_data)

		if provider.api_endpoint_args:
			out[provider.name]["api_endpoint_args"] = json.loads(provider.api_endpoint_args)
	
	return out

def is_full_url(url: str):
	return url.startswith("https://") or url.startswith("http://")

def is_wxwork_browser():
	request_dict = frappe.request.__dict__
	user_agent = request_dict.get("environ", {}).get("HTTP_USER_AGENT", "").lower()
	return "wxwork" in user_agent

def is_wechat_browser():
	request_dict = frappe.request.__dict__
	user_agent = request_dict.get("environ", {}).get("HTTP_USER_AGENT", "").lower()
	return "micromessenger" in user_agent

oauth.get_oauth2_providers = get_oauth2_providers
oauth.get_oauth2_authorize_url = get_oauth2_authorize_url